
#include "Player.h"
#include <mmsystem.h>

CPlayer::CPlayer()
{
	
	m_playerMod = NULL;
	m_currentAnimation = SEQ_IDLE;

	for( int i = 0;i<MAX_SEQUANCE;i++){
		m_animList[i] = NULL;
	}

	m_t = 0;
}

void CPlayer::CreateModel( const TCHAR* filename )
{
	if( m_playerMod){
		Destroy();
	}

	m_playerMod = new CHrkModel;
	m_playerMod->LoadFile( filename );
}

CHrkAnim* CPlayer::CreateAnimation( PLAYER_SEQUANCE seq,const TCHAR* filename )
{
	if( m_animList[seq] ){
		m_animList[seq] ->Destroy();
		delete m_animList[seq];
	}
	
	m_animList[seq] = new CHrkAnim;
	m_animList[seq]->m_nodeRoot = m_playerMod->m_root_node;
	m_animList[seq]->LoadFromFile( filename );
	return m_animList[seq];
	
}

void CPlayer::SetCurrrentAnimation( PLAYER_SEQUANCE seq ){ 

	if( m_currentAnimation!=seq){
		BreakSequance();
		m_currentAnimation = seq ;

		if(seq == SEQ_WALK_BACKWARD ){
			m_t = m_animList[SEQ_WALK_BACKWARD]->GetTimeLength()-0.01;
		
		}
		else{
			m_t = 0.f;
		}
	}
}

void CPlayer::Update()
{
	glPushMatrix();
	
	CHrkAnim* anim = m_animList[m_currentAnimation];
	static DWORD t1 = timeGetTime(); 
	DWORD t = timeGetTime();
	
	float elapsedTime = t - t1;
	t1 = t;

	m_t += elapsedTime/1000.f;

	float frameTick = anim->GetFrameTick();
	float timeLength = anim->GetTimeLength();
	
	bool bRewind = false;
	if( m_t > timeLength) {
		m_t = fmod(m_t,timeLength);	
		RewindSequance();
	
	}

	anim->UpdateAnim( m_t );

	m_playerMod->Update();	
	m_playerMod->Draw();

	glPopMatrix();
}

void CPlayer::Draw()
{
}

void CPlayer::Destroy()
{
}

void CPlayer::SetPosition( GLvec3f pos )
{
	m_playerMod->m_root_node->m_translate = pos;
}

GLvec3f CPlayer::GetPosition()
{
	return m_playerMod->m_root_node->m_translate;
}
void CPlayer::SetOrientation( GLvec3f angle )
{
	m_playerMod->m_root_node->m_rotate = angle;
}

GLvec3f CPlayer::GetOrientation()
{
	return m_playerMod->m_root_node->m_rotate;
}

void CPlayer::SetScale( GLvec3f scale )
{
	m_playerMod->m_root_node->m_scale = scale;
}

GLvec3f CPlayer::GetScale()
{
	return m_playerMod->m_root_node->m_scale;
}

void CPlayer::GetCurrentRotate(float& rx,float& ry,float& rz)
{		
	float rx1,ry1,rz1;

	rx = 0.f;
	ry = 0.f;
	rz = 0.f;
	
	CHrkAnim* anim = m_animList[m_currentAnimation];
	CHrkNodeAnim* bip01 = anim->FindNodeAnim("Bip01");

	if( bip01->HaveRotAnim()){	
		bip01->m_rotKeysQ[0].val.ToEuler( rx1,ry1,rz1 );
		bip01->m_rotKeysQ.m_valInterp.ToEuler( rx,ry,rz );
		rx -= rx1;
		ry -= ry1;
		rz -= rz1;
	}
}
void CPlayer::GetCurrentMove( float& mx,float& my)
{
	float x,y,z;
	x = 0.f;
	y = 0.f;
	z = 0.f;

	int nKeys = 0;

	CHrkAnim* anim = m_animList[m_currentAnimation];
	CHrkNodeAnim* bip01 = anim->FindNodeAnim("Bip01");

	if(!bip01){
		mx = my = 0.f;
		return;
	}

	if( m_currentAnimation == SEQ_WALK_BACKWARD ){
		nKeys = bip01->m_posKeys[0].size();
		
		if( nKeys ){
			x = bip01->m_posKeys[0].m_valInterp  - bip01->m_posKeys[0][nKeys-1].val;;
		}

		nKeys = bip01->m_posKeys[1].size();
		
		if( nKeys ){
			y = bip01->m_posKeys[1].m_valInterp - bip01->m_posKeys[1][nKeys-1].val;
		}

		nKeys = bip01->m_posKeys[2].size();
		
		if( nKeys ){
			z = bip01->m_posKeys[2].m_valInterp - bip01->m_posKeys[2][nKeys-1].val;
		}

	}
	else{
	
		nKeys = bip01->m_posKeys[0].size();
		
		if( nKeys ){
			x = bip01->m_posKeys[0].m_valInterp  - bip01->m_posKeys[0][0].val;;
		}

		nKeys = bip01->m_posKeys[1].size();
		
		if( nKeys ){
			y = bip01->m_posKeys[1].m_valInterp - bip01->m_posKeys[1][0].val;
		}

		nKeys = bip01->m_posKeys[2].size();
		
		if( nKeys ){
			z = bip01->m_posKeys[2].m_valInterp - bip01->m_posKeys[2][0].val;
		}

	}

	
	x *= m_playerMod->m_root_node->m_scale.x;
	z *= m_playerMod->m_root_node->m_scale.z;

	float ay = m_playerMod->m_root_node->m_rotate.y;

	ay = fmod(ay,(float)M_PI*2.f);

	float m = sqrt( x*x + z*z );
	if( m_currentAnimation == SEQ_WALK_BACKWARD ){
		m = m;
	}

	mx = sin(ay)*m;
	my = cos(ay)*m;
}

void CPlayer::BreakSequance()
{
	CHrkAnim* anim = m_animList[m_currentAnimation];
	CHrkNodeAnim* bip01 = anim->FindNodeAnim("Bip01");

	if(bip01){

		
		float rx,ry,rz;

		

		if( bip01->HaveRotAnim()){	
			GetCurrentRotate( rx,ry,rz );				
			m_playerMod->m_root_node->m_rotate.y += ry;			
		}

		float mx = 0.f,my = 0.f;

		if( bip01->HavePosAnim()){

			GetCurrentMove( mx,my );

			m_playerMod->m_root_node->m_translate.x += mx;
			m_playerMod->m_root_node->m_translate.z += my;	
		}

	}
}

void CPlayer::RewindSequance()
{
	CHrkAnim* anim = m_animList[m_currentAnimation];
	CHrkNodeAnim* bip01 = anim->FindNodeAnim("Bip01");
	
	if(bip01){
		
		float x,y,z,rx,ry,rz;

		x = 0.f;
		y = 0.f;
		z = 0.f;
		
		rx = 0.f;
		ry = 0.f;
		rz = 0.f;

		int nKeys = bip01->m_posKeys[0].size();
		
		if( nKeys ){
			x = bip01->m_posKeys[0][nKeys-1].val  - bip01->m_posKeys[0][0].val;;
		}

		nKeys = bip01->m_posKeys[1].size();
		
		if( nKeys ){
			y = bip01->m_posKeys[1][nKeys-1].val - bip01->m_posKeys[1][0].val;
		}

		nKeys = bip01->m_posKeys[2].size();
		
		if( nKeys ){
			z = bip01->m_posKeys[2][nKeys-1].val  - bip01->m_posKeys[2][0].val;
		}

		nKeys = bip01->m_rotKeysQ.size();

		if( nKeys ){	
			float rx1,ry1,rz1;
			bip01->m_rotKeysQ[0].val.ToEuler( rx1,ry1,rz1 );
			bip01->m_rotKeysQ[nKeys-1].val.ToEuler( rx,ry,rz );

			rx -= rx1;
			ry -= ry1;
			rz -= rz1;
		}

		x *= m_playerMod->m_root_node->m_scale.x;
		z *= m_playerMod->m_root_node->m_scale.z;
		
		if( m_currentAnimation == SEQ_TURN_LFET){		
			m_playerMod->m_root_node->m_rotate.y += ry;			
		}
		else if(m_currentAnimation == SEQ_TURN_RIGHT)
		{
			m_playerMod->m_root_node->m_rotate.y -= ry;		
		}

		if( m_currentAnimation == SEQ_WALK_FORWARD || m_currentAnimation == SEQ_WALK_BACKWARD){	

			float ay = m_playerMod->m_root_node->m_rotate.y;

			ay = fmod(ay,(float)M_PI*2.f);
	
			float m = sqrt( x*x + z*z );
			if( m_currentAnimation == SEQ_WALK_BACKWARD ){
				m = -m;
			}

			m_playerMod->m_root_node->m_translate.x += sin(ay)*m;
			m_playerMod->m_root_node->m_translate.z += cos(ay)*m;		
		}
	
	}
}